package com.unittec.drainage.provider.manage.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.unittec.drainage.provider.manage.entity.RegionGeom;
import com.unittec.drainage.provider.manage.utils.JtsUtils;
import com.unittec.drainage.provider.manage.utils.coordinates.CoordinatesUtils;
import com.unittec.drainage.provider.utils.CopyListUtils;
import com.unittec.drainage.provider.utils.CopyUtils;
import com.unittec.drainage.provider.utils.UUIDUtils;
import com.unittec.drainage.sdk.manage.request.Req301001;
import com.unittec.drainage.sdk.manage.vo.RegionTreeVo;
import com.unittec.drainage.sdk.manage.request.Req301002;
import com.unittec.drainage.sdk.manage.request.Req301003;
import com.unittec.drainage.sdk.manage.request.Req301004;
import com.unittec.drainage.sdk.manage.request.Req301005;
import com.unittec.drainage.sdk.manage.vo.RegionVo;
import com.unittec.drainage.sdk.root.internal.exception.BusinessException;
import com.vividsolutions.jts.geom.Geometry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.unittec.drainage.provider.manage.entity.Region;
import com.unittec.drainage.provider.manage.mapper.RegionMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * @author Jason
 * @date 2021/8/6
 */
@Service
public class RegionService extends ServiceImpl<RegionMapper, Region> {

    @Autowired
    private RegionGeomService regionGeomService;

    /**
     * 查询区域树形列表
     *
     * @param type
     * @return
     */
    public List<RegionTreeVo> queryTreeList(String type) {
        QueryWrapper<Region> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(Region::getSort);
        if (StrUtil.isNotBlank(type)) {
            queryWrapper.lambda().eq(Region::getType, type);
        }
        List<Region> regionList = this.list(queryWrapper);
        List<RegionTreeVo> regionTreeVoList = CopyListUtils.copyList(regionList, RegionTreeVo.class);
        List<RegionGeom> regionGeomList = regionGeomService.selectAll();
        for (RegionTreeVo region : regionTreeVoList) {
            List<JSONArray> coordinatesList = new ArrayList<>();
            for (RegionGeom regionGeom: regionGeomList.stream().filter(regionGeom -> region.getId().equals(regionGeom.getRegionId())).collect(Collectors.toList())) {
                if (regionGeom.getGeom() != null) {
                    coordinatesList.add(CoordinatesUtils.GeometrySwitchByCoordinates(regionGeom.getGeom()));
                }
            }
            region.setCoordinatesList(coordinatesList);
        }
        Map<String, List<RegionTreeVo>> map = regionTreeVoList.stream().collect(Collectors.groupingBy(RegionTreeVo::getParentId));
        map.forEach((k, v) -> v.sort(Comparator.comparing(RegionTreeVo::getSort)));
        regionTreeVoList.stream().forEach(regionTreeVo -> regionTreeVo.setChildren(map.get(regionTreeVo.getId())));
        return regionTreeVoList.stream().filter(regionTreeVo -> "".equals(regionTreeVo.getParentId())).collect(Collectors.toList());
    }

    /**
     * 查询区域列表
     *
     * @param req301001
     * @return
     */
    public List<RegionVo> regionList(Req301001 req301001) {
        List<RegionVo> list = new ArrayList<>();
        QueryWrapper<Region> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(Region::getSort);
        if (StrUtil.isNotBlank(req301001.getParentId())) {
            queryWrapper.lambda().eq(Region::getParentId, req301001.getParentId());
        }
        if (StrUtil.isNotBlank(req301001.getType())) {
            queryWrapper.lambda().eq(Region::getType, req301001.getType());
        }
        List<Region> regionList = this.list(queryWrapper);
        List<RegionGeom> regionGeomList = regionGeomService.selectAll();
        for (Region region : regionList) {
            RegionVo regionVo = new RegionVo();
            CopyUtils.copyProperties(region, regionVo);
            List<JSONArray> coordinatesList = new ArrayList<>();
            for (RegionGeom regionGeom: regionGeomList.stream().filter(regionGeom -> region.getId().equals(regionGeom.getRegionId())).collect(Collectors.toList())) {
                if (regionGeom.getGeom() != null) {
                    coordinatesList.add(CoordinatesUtils.GeometrySwitchByCoordinates(regionGeom.getGeom()));
                }
            }
            regionVo.setCoordinatesList(coordinatesList);
            list.add(regionVo);
        }
        return list;
    }

    /**
     * 添加区域
     *
     * @param req301002
     */
    @Transactional(rollbackFor = Exception.class)
    public void addRegion(Req301002 req301002) {
        String id = UUIDUtils.getId();
        Region region = new Region();
        region.setId(id);
        CopyUtils.copyProperties(req301002, region);
        this.save(region);
        List<RegionGeom> regionGeomList = new ArrayList<>();
        List<JSONArray> coordinatesList = req301002.getCoordinatesList();
        if (!CollectionUtils.isEmpty(coordinatesList)) {
            for (JSONArray coordinates : coordinatesList) {
                RegionGeom regionGeom = new RegionGeom();
                regionGeom.setId(UUIDUtils.getId());
                regionGeom.setRegionId(id);
                regionGeom.setGeom(CoordinatesUtils.initPolygonGeometry(coordinates));
                regionGeomList.add(regionGeom);
            }
        }
        if (!CollectionUtils.isEmpty(regionGeomList)) {
            regionGeomService.batchInsert(regionGeomList, JtsUtils.SRID_4547);
        }
    }

    /**
     * 修改区域属性
     *
     * @param req301003
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRegionAttribute(Req301003 req301003) {
        Region region = new Region();
        CopyUtils.copyProperties(req301003, region);
        this.updateById(region);
    }

    /**
     * 修改区域坐标
     *
     * @param req301004
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRegionCoordinates(Req301004 req301004) {
        String regionId = req301004.getId();
        regionGeomService.remove(new LambdaQueryWrapper<RegionGeom>().eq(RegionGeom::getRegionId, regionId));
        List<RegionGeom> regionGeomList = new ArrayList<>();
        List<JSONArray> coordinatesList = req301004.getCoordinatesList();
        if (!CollectionUtils.isEmpty(coordinatesList)) {
            for (JSONArray coordinates : coordinatesList) {
                RegionGeom regionGeom = new RegionGeom();
                regionGeom.setId(UUIDUtils.getId());
                regionGeom.setRegionId(regionId);
                regionGeom.setGeom(CoordinatesUtils.initPolygonGeometry(coordinates));
                regionGeomList.add(regionGeom);
            }
        }
        if (!CollectionUtils.isEmpty(regionGeomList)) {
            regionGeomService.batchInsert(regionGeomList, JtsUtils.SRID_4547);
        }
    }

    /**
     * 删除区域
     *
     * @param req301005
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteRegion(Req301005 req301005) {
        String regionId = req301005.getId();
        this.removeById(regionId);
        regionGeomService.remove(new LambdaQueryWrapper<RegionGeom>().eq(RegionGeom::getRegionId, regionId));
    }

    /**
     * 根据id获取区域详情
     *
     * @param id
     * @return
     */
    public RegionVo getRegionDetails(String id) {
        RegionVo regionVo = new RegionVo();
        Region region = this.getById(id);
        if (region == null) {
            throw new BusinessException("区域id不存在");
        }
        CopyUtils.copyProperties(region, regionVo);
        List<JSONArray> coordinatesList = new ArrayList<>();
        List<RegionGeom> regionGeomList = regionGeomService.selectAllByRegionId(id);
        if (!CollectionUtils.isEmpty(regionGeomList)) {
            for (RegionGeom regionGeom: regionGeomList) {
                if (regionGeom.getGeom() != null) {
                    coordinatesList.add(CoordinatesUtils.GeometrySwitchByCoordinates(regionGeom.getGeom()));
                }
            }
        }
        regionVo.setCoordinatesList(coordinatesList);
        return regionVo;
    }
}
